/**************************************************************
    LinuxBox Connection Pool

    Two static methods could be used:
    1.  getConnection()
    2.  releaseConneciton()

***************************************************************/

package linuxbox.util;

import java.sql.*;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;

import linuxbox.BoxStatic;

public class ConnectionPool extends ObjectPool {
    protected static Logger logger = Logger.getLogger(ConnectionPool.class.getName());
    private static boolean m_bInited = false;
    private static String m_sDSN;
    private static String m_sJDBCDrv;
    private static String m_username;
    private static String m_password;
    private static int count = 0;

    public static ConnectionPool getInstance() {
        return new ConnectionPool();
    }

    private void initCP() throws SQLException {
        try {
            logger.debug("Driver=" + m_sJDBCDrv);
            logger.debug("DSN=" + m_sDSN);

            Class.forName(m_sJDBCDrv).newInstance();
            m_bInited = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected ConnectionPool() {
        m_sDSN      = BoxStatic.dbUrl;
        m_sJDBCDrv  = BoxStatic.dbDriver;
        m_username  = BoxStatic.username;
        m_password  = BoxStatic.password;
    }

    protected Object objCreate() throws SQLException {
        logger.debug("new connection" + (count++) + " DSN=" + m_sDSN);
        Object obj = null;

        obj = (DriverManager.getConnection(m_sDSN, m_username, m_password));
        /*try {
              obj = (DriverManager.getConnection(m_sDSN,m_username,m_password));
        } catch (SQLException e ) {
        ////////////////////////////////////////////////////////////////
        // The following are for debugging in VJ, to use ms driver
            try {
                m_sJDBCDrv = PoolConst.CONNJDBCDRV1;
                Class.forName(m_sJDBCDrv).newInstance();
                m_bInited = true;
            } catch (Exception e1) {
                e1.printStackTrace();
            }

            obj = (DriverManager.getConnection(m_sDSN,m_username,m_password));
            return obj;
        ///////////////////////////////////////////////////
        }*/

        return obj;
    }

    protected boolean objValidate(Object obj) {
        try {
            if (obj == null) return false;
            Connection conn = (Connection)obj;
            if (conn.isClosed()) return false;
            Statement stat = conn.createStatement();
            if (stat == null) return false;
            stat.close();
            return true;
        } catch(Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    protected void objExpire(Object obj) {
        try {
          logger.debug("Expired and Close connection" + obj);
           if (obj != null) {
                ((Connection)obj).close();
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public synchronized Connection getConnection() throws SQLException, Exception {
        if (!m_bInited)
            initCP();

        return((Connection)checkOut());
    }

    public synchronized void releaseConnection(Connection conn) throws Exception {
        if (!m_bInited)
            throw new Exception("release object without init!");

        checkIn(conn);
    }

    public void showUsage() throws Exception {
        int poolSize = pool.size();
        int total = poolSize + usageCount;
        logger.info("total size is " + total + " and pool size is " + poolSize
             + " and usage is " + usageCount);
    }

    public synchronized void clearConnPool() throws Exception {
        for (Iterator it = pool.iterator(); it.hasNext(); ) {
            ObjectWrapper ow = (ObjectWrapper)it.next();
            Connection conn = (Connection)ow.getObject();
            it.remove();
            if (conn != null) {
                conn.close();
                conn = null;
            }
        }
    }
}
